/*
 * Filename: g:\espidf_workspace\idf_S3_T-Watch\main\network\wifi.cc
 * Path: g:\espidf_workspace\idf_S3_T-Watch\main\network
 * Created Date: Monday, June 23rd 2025, 3:26:06 pm
 * Author: sss
 *
 * Copyright (c) 2025 Your Company
 */
#include "wifi.h"
#include "esp_log.h"
#include "esp_err.h"
#include "utils.h"
#include "esp_wifi.h"
#include "esp_wifi_types_generic.h"
#include "string.h"
#include "esp_smartconfig.h"
#include "smartconfig_ack.h"
#include "string.h"
static const char *TAG = "Wifi";

static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
    Wifi& wifi = Wifi::get_instance();

    if (event_base == WIFI_EVENT)
    {
        switch (event_id)
        {
        case WIFI_EVENT_STA_START:
            ESP_LOGI(TAG, "WIFI_EVENT_STA_START");
            // esp_wifi_connect();  // WiFi启动后自动连接
            break;
        case WIFI_EVENT_STA_CONNECTED:
            ESP_LOGI(TAG, "Connected to AP");
            break;
        case WIFI_EVENT_STA_DISCONNECTED:
            ESP_LOGI(TAG, "Disconnected");
            ESP_LOGI(TAG, "Reconnect to AP 3s later");

            vTaskDelay(pdMS_TO_TICKS(3000));
            wifi.connect();
            break;
        default:
            break;
        }
    }
    else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
    {
        ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
        ESP_LOGI(TAG, "Got IP: " IPSTR, IP2STR(&event->ip_info.ip));
        wifi.is_connected_flag = true;
        char ip_str[16]; // Enough for "xxx.xxx.xxx.xxx"
        snprintf(ip_str, sizeof(ip_str), IPSTR, IP2STR(&event->ip_info.ip));
        ESP_LOGI(TAG, "IP address: %s", ip_str);
        strncpy(wifi.ip_address, ip_str, strlen(ip_str));
    }
    else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_LOST_IP)
    {
        ESP_LOGI(TAG, "Lost IP");
        wifi.is_connected_flag = false;
        strncpy(wifi.ip_address, "" ,0);
    }
}

static void handler_got_ssid_passwd(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
    smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)data;
    uint8_t ssid[33] = {0};
    uint8_t password[65] = {0};
    uint8_t cellphone_ip[4];
    esp_err_t err = ESP_OK;

    memcpy(ssid, evt->ssid, sizeof(evt->ssid));
    memcpy(password, evt->password, sizeof(evt->password));
    memcpy(cellphone_ip, evt->cellphone_ip, sizeof(evt->cellphone_ip));

    ESP_LOGI(TAG, "SSID:%s", ssid);
    ESP_LOGI(TAG, "PASSWORD:%s", password);
    ESP_LOGI(TAG, "Phone ip: %d.%d.%d.%d\n", cellphone_ip[0], cellphone_ip[1], cellphone_ip[2], cellphone_ip[3]);

    err = sc_send_ack_start(evt->type, evt->token, evt->cellphone_ip);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Send smartconfig ACK error: %d", err);
    }

    wifi_config_t wifi_config = {
        .sta = {
            .ssid = "0",
            .password = "0",
            .threshold = {
                .authmode = WIFI_AUTH_WPA2_PSK, // 加密方式（推荐WPA2）
            },
        },
    };
    memcpy(wifi_config.sta.ssid, ssid, sizeof(ssid));
    memcpy(wifi_config.sta.password, password, sizeof(password));
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));

    Wifi& wifi = Wifi::get_instance();
    wifi.smartconfig_stop();
    wifi.connect();
}


 



Wifi::Wifi()
{
    Util_nvs &nvs = Util_nvs::get_instance();
    // 初始化TCP/IP协议栈
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_create_default_wifi_sta();


    // 初始化WiFi
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));


    ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_FLASH)); // 设置WiFi存储方式为RAM


    // 注册WiFi和IP事件处理函数
    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, NULL));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL, NULL));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_LOST_IP, &wifi_event_handler, NULL, NULL));

    
    // 设置WiFi模式并启动
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_start());
}
Wifi::~Wifi() {}

bool Wifi::is_connected()
{
    wifi_ap_record_t ap_info;
    esp_err_t ret = esp_wifi_sta_get_ap_info(&ap_info);
    if (ret == ESP_OK)
    {
        const char *ssid = (char *) ap_info.ssid;
        if (strlen(ssid) > 0 && is_connected_flag)
        {
            ESP_LOGI(TAG, "Connected to SSID: %s, RSSI: %d", ap_info.ssid, ap_info.rssi);
            return true;
        }else{
            ESP_LOGI(TAG, "Connected to SSID: %s, RSSI: %d", ap_info.ssid, ap_info.rssi);
            return false;
        }
        
    }
    else
    {
        ESP_LOGI(TAG, "Not connected to any AP %s", esp_err_to_name(ret));
        return false;
    }
}
void Wifi::connect(const char *ssid, const char *password)
{
    if (!ssid || strlen(ssid) == 0)
    {
        return;
    }

    wifi_config_t wifi_config = {
        .sta = {
            .ssid = "",
            .password = "",
            .threshold = {
                .authmode = WIFI_AUTH_WPA2_PSK, // 加密方式（推荐WPA2）
            },
        },
    };
    memcpy(wifi_config.sta.ssid, ssid, strlen(ssid));
    memcpy(wifi_config.sta.password, password, strlen(password));
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
    connect();
}
void Wifi::connect()
{   
    wifi_mode_t wifi_mode;
    ESP_ERROR_CHECK(esp_wifi_get_mode(&wifi_mode));
    if (wifi_mode != WIFI_MODE_STA)
    {
        ESP_LOGI(TAG, "change wifi mode to WIFI_MODE_STA");
        ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    }
    esp_err_t ret = esp_wifi_connect();
    if (ret == ESP_OK)
    {
        ESP_LOGI(TAG, "connect to ap success");
    }
    else
    {
        ESP_LOGI(TAG, "connect to ap fail %s" , esp_err_to_name(ret));
    }

}
void Wifi::disconnect()
{
    ESP_ERROR_CHECK(esp_wifi_disconnect());
}

void Wifi::smartconfig_start()
{
    ESP_ERROR_CHECK(esp_wifi_stop()); // 停止WiFi
    // 设置WiFi模式并启动
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_start());

    ESP_ERROR_CHECK(esp_smartconfig_set_type(SC_TYPE_ESPTOUCH_V2)); // 使用ESP-TOUCH V2协议
    const smartconfig_start_config_t smart_config = {
        .enable_log = false,                /**< Enable smartconfig logs. */
        .esp_touch_v2_enable_crypt = false, /**< Enable ESPTouch v2 crypt. */
        .esp_touch_v2_key = {0},            /**< ESPTouch v2 key. */
    };

    ESP_ERROR_CHECK(esp_event_handler_register(SC_EVENT, SC_EVENT_GOT_SSID_PSWD, handler_got_ssid_passwd, NULL));

    ESP_ERROR_CHECK(esp_smartconfig_start(&smart_config));
}

void Wifi::smartconfig_stop()
{
    ESP_ERROR_CHECK(esp_smartconfig_stop());           // 停止SmartConfig
    ESP_ERROR_CHECK(esp_wifi_stop());                  // 停止WiFi
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); // 设置WiFi模式为STA
    ESP_ERROR_CHECK(esp_wifi_start());                 // 启动WiFi
}